package com.bank.common.dao;

import cn.hutool.core.collection.CollectionUtil;
import com.bank.common.constant.Constant;
import com.bank.common.dao.mapper.TkMapper;
import com.bank.common.dao.model.BaseModel;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.entity.Example;

import java.lang.reflect.ParameterizedType;
import java.time.Instant;
import java.util.List;

/**
 * 类TkDao.java的实现描述：基础公共DAO
 *
 * @author zach
 * @Date :2020-06-10 11:02.
 */
public class TkDao<M extends TkMapper<T>,T extends BaseModel> {

    @Autowired
    public M baseMapper;

    private Class<T> tType = null;


    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    public T selectByPrimaryKey(Long id){
        T model =  baseMapper.selectByPrimaryKey(id);
        if(model!=null&&Constant.DELETE.equals(model.getDflag())){
            return null;
        }
        return model;
    }

    /**
     * 查询多条数据
     * @param ids
     * @return
     */
    public List<T> selectByPrimaryKeys(List<String> ids){
        Example example = getExample();
        if(CollectionUtil.isNotEmpty(ids)){
            example.and().andIn("id",ids);
        }
        return baseMapper.selectByExample(example);
    }

    /**
     * 通过实体作为筛选条件查询
     *
     * @param model 实例对象
     * @return 对象列表
     */
    public List<T> select(T model){
        model.setDflag(Constant.NOT_DELETE);
        return baseMapper.select(model);
    }

    public List<T> selectAll(){
        T t = getModel();
        t.setDflag(Constant.NOT_DELETE);
        return select(t);
    }

    /**
     * 通过实体作为筛选条件查询
     *
     * @param model 实例对象
     * @return 对象列表
     */
    public T selectOne(T model){
        List<T> list = select(model);
        if(CollectionUtil.isEmpty(list)){
            return null;
        }
        return list.get(0);
    }

    /**
     * 新增数据
     *
     * @param model 实例对象
     * @return 影响行数
     */
    public T insert(T model){
        model.setGmtModified(Instant.now());
        model.setGmtCreated(Instant.now());
        model.setDflag(Constant.NOT_DELETE);
        baseMapper.insert(model);
        return model;
    }

    public int insertList(List<T> models){
        if(CollectionUtil.isEmpty(models)){
            return 0;
        }
        for(T model :models){
            model.setGmtModified(Instant.now());
            model.setGmtCreated(Instant.now());
            model.setDflag(Constant.NOT_DELETE);
        }
        return baseMapper.insertListNoSkipId(models);
    }

    /**
     * 修改数据
     *
     * @param model 实例对象
     * @return 影响行数
     */
    public int updateByPrimaryKeySelective(T model){
        model.setGmtModified(Instant.now());
        return  baseMapper.updateByPrimaryKeySelective(model);
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 影响行数
     */
    public int deleteById(Long id){
        T model = getModel();
        model.setId(id);
        model.setGmtModified(Instant.now());
        model.setDflag(Constant.DELETE);
        return  updateByPrimaryKeySelective(model);
    }


    @SneakyThrows
    private T getModel(){
        if(tType ==null){
            ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass();
            tType = (Class<T>) superClass.getActualTypeArguments()[1];
        }
        T model =  tType.newInstance();
        return model;
    }

    public Example getExample(){
        Example example = new Example(getType());
        example.and().andEqualTo("dflag", Constant.NOT_DELETE);
        return example;
    }

    private Class<T> getType(){
        if(tType ==null){
            ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass();
            this.tType = (Class<T>) superClass.getActualTypeArguments()[1];
        }
        return this.tType;
    }
}
